package com.ly.mpayment.rest.up.zhengbang;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Multimap;
import com.ly.mpayment.core.secuity.MD5;
import com.ly.mpayment.core.util.*;
import com.ly.mpayment.persist.entity.UpOrder;
import com.ly.mpayment.persist.entity.UpShopInfo;
import com.ly.mpayment.persist.service.downrechargeflow.IDownRechargeFlowService;
import com.ly.mpayment.persist.service.downshopinfo.IDownShopInfoService;
import com.ly.mpayment.persist.service.uporder.IUporderService;
import com.ly.mpayment.persist.service.upshopinfo.IUpShopInfoService;
import com.ly.mpayment.rest.recharge.RechargeRest;
import org.apache.log4j.Logger;
import org.mortbay.util.MultiMap;
import org.mortbay.util.UrlEncoded;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.io.UnsupportedEncodingException;
import java.util.*;

@Component
@Path("zhengbang")
public class ZhengBangRest {

	Logger logger = Logger.getLogger(ZhengBangRest.class);


	@Autowired
	IUporderService upOrderService;

	@Autowired
	IDownRechargeFlowService flowService;

	@Autowired
	IDownShopInfoService shopService;

	@Autowired
	IUpShopInfoService upShopInfoService;

	/**
	 * 字段名称	字段说明	类型	必填	备注
	 * agentAcct	代理账号	string(30)	Y	-
	 * orderId	订单编号	string(30)	Y	-
	 * status	订单状态	string(30)	Y	详见订单状态编码列表
	 * voucher	充值凭证	string(50)	Y	充值成功时返回
	 * sign	签名	string(32)	Y	MD5加密，详见签名规则
	 * agentAcct=18181451525&orderId=2c922ab77766cdd3017766d301fd000f&sign=103f3576faf9f67b615f7dbaf290cdde&status=F&voucher=
	 * @return
	 */
	@Path("callBack")
	@POST
	public synchronized String callBack(@RequestBody String body){
		logger.info("zhengbang:"+body);
		MultiMap multimap = parceString(body);
		if(!StringUtils.isBlank(body)){
			UpOrder order = upOrderService.findById(multimap.getString("orderId"));
			if (order != null && multimap.getString("status").equals("S") && order.getStatus() == Config.status[0]) {
				order.setRemark(multimap.containsKey("voucher") ? multimap.getString("voucher") : multimap.getString("status"));
				RechargeRest.successUpOrder.add(order);
				UpShopInfo upShopInfo = this.upShopInfoService.findByUserId(order.getUserOrder().getUseruuid());
				JSONObject data = new JSONObject();
				data.put("agentAcct",upShopInfo.getAppId());
				data.put("orderId",order.getUporderuuid());
				data.put("retCode","SUCCESS");
				data.put("sign",this.sign(data,"key",upShopInfo.getUpkey()));
				return data.toJSONString();
			}else if(order != null && order.getStatus() == Config.status[0] && multimap.getString("status").equals("F")){
				order.setRemark(multimap.containsKey("retMsg") ? multimap.getString("retMsg") :  multimap.getString("status"));
				RechargeRest.failtUpOrder.add(order);
				JSONObject data = new JSONObject();
				UpShopInfo upShopInfo = this.upShopInfoService.findByUserId(order.getUserOrder().getUseruuid());
				data.put("agentAcct",upShopInfo.getAppId());
				data.put("orderId",order.getUporderuuid());
				data.put("retCode","SUCCESS");
				data.put("sign",this.sign(data,"key",upShopInfo.getUpkey()));
				return data.toJSONString();
			}else{
				logger.info("zhengbang_not_found_order:" + body +","+ (order == null ? " order is null" : order.getUpphonenum() ));
			}
		}
		return "FAILED";
	}

	private MultiMap parceString(String str){
		MultiMap map = new MultiMap();
		UrlEncoded.decodeTo(str, map, "utf-8");
		return map;
	}

	/**
	 * 签名
	 * @param jsonObject
	 * @param key
	 * @return
	 */
	private String sign(JSONObject jsonObject, String key,String keyValue){
		//将所有请求的参数放进TreeMap，TreeMap默认按照key升序排列
		Map<String, String> map = new TreeMap<>();
		for(String s : jsonObject.keySet()){
			map.put(s,jsonObject.getString(s));
		}

		StringBuilder sb = new StringBuilder();
		//循环拼接所有value
		for (String k : map.keySet()) {
			sb.append(k);
			sb.append("=");
			sb.append(map.get(k));
			sb.append("&");
		}
		//最后拼接上秘钥
		sb.append(key);
		sb.append("=");
		sb.append(keyValue);
		logger.info("签名前：" + sb.toString());
		return MD5.md5(sb.toString());
	}

	/**
	 * 字段名称	字段说明	类型	必填	备注
	 * agentAcct	账号	string(30)	Y	需申请开通
	 * orderId	订单编号	string(30)	Y	需保障唯一性
	 * bizType	业务类型	string(30)	Y	详见业务编码列表
	 * phoneNum	充值号码	string(11)	Y	11位手机号码。(当phoneType为固话或宽带充值时，充值号码前面必须加上区号，最大限制15位)
	 * phoneType	号码类型	string(10)	N	详见“号码类型编码列表”；不填默认以本平台为准
	 * amount	充值金额	int(10)	Y	单位:元
	 * timestamp	请求时间戳	long(13)	Y	单位:毫秒
	 * sign	签名	string(32)	Y	MD5加密，详见签名规则
	 *
	 * 字段名称	字段说明	类型	必填	备注
	 * agentAcct	账号	string(30)	Y	-
	 * orderId	订单编号	string(30)	Y	-
	 * retCode	响应编码	string(30)	Y	详见响应编码列表
	 * retMsg	响应描述	string(50)	Y	不参与签名
	 * sign	签名	string(32)	Y	MD5加密，详见签名规则
	 * @return
	 */
	public void commitOrder(UpOrder order, UpShopInfo shop) {
		UpOrder product = this.upOrderService.findOrderProduct(order.getUporderuuid());
		if (product != null) {
			JSONObject data = new JSONObject();
			data.put("agentAcct",shop.getAppId());
			data.put("orderId",order.getUporderuuid());
			data.put("bizType","E_CHARGE");
			data.put("phoneNum",order.getUpphonenum());
			data.put("amount",product.getUpShopPro().getUpfacevalue());
			data.put("timestamp",System.currentTimeMillis());
			data.put("sign",this.sign(data,"key",shop.getUpkey()));
			String res = HttpClient.postUrl(shop.getOrderCommitAddress(),StringSort.jsonToString(data));
			logger.info("commitZhengBang_result:" + data +",phone:"+order.getUpphonenum()+",res:"+res);
			if (!StringUtils.isBlank(res)) {
				JSONObject result = JSONObject.parseObject(res);
				if(result.containsKey("retCode") && result.getString("retCode").equals("SUCCESS")){
					upOrderService.updateUpOrderMsg(order, result.getString("orderId"),result.getString("retMsg"));
				}else if (result.containsKey("retCode") && codesError.contains(result.getString("retCode"))) {
					order.setRemark(result.containsKey("retMsg") ?	result.getString("retMsg") : Config.orderFailA);
					RechargeRest.failtUpOrder.add(order);
				}
			} else {
				upOrderService.commitFailt(order,  Config.commitFailt);
				logger.info("commitZhengBang_error" + order.getUpphonenum());
			}
		}
	}

	/**
	 * 提单错误直接失败
	 */
	private static Set<String> codesError = new HashSet<String>(){{
		add("NOT_UTF8");
		add("REQUEST_FREQUENTLY");
		add("TRADE_TIME_CLOSED");
		add("GLOBAL_CHANNEL_CLOSED");
		add("INVALID_NUMBER");
		add("PARAM_ERROR");
		add("SIGN_ERROR");
		add("LACK_PARAMS");
		add("AGENT_NOT_EXIST");
		add("AGENT_ORDERID_USED");
		add("REQUIRE_POST_METHOD");
		add("ILLEGAL_REQUEST");
		add("ORDER_NOT_EXISTS");
	}};


	/**
	 * SUCCESS	成功	提交成功	表示请求接口成功	-
	 * NOT_UTF8	编码格式错误	提交失败	未使用指定编码	请使用UTF-8编码格式
	 * REQUEST_FREQUENTLY	请求太频繁	提交失败	同一订单查询（冲正）过于频繁	10s内同一订单只允许查询（冲正）一次
	 * TRADE_TIME_CLOSED	交易关闭时间	提交失败	23:50-00:20期间提交下单请求	请在正常交易时间再试
	 * GLOBAL_CHANNEL_CLOSED	渠道关闭	提交失败	系统维护	系统恢复后重新尝试下单
	 * INVALID_NUMBER	无效的充值号码	提交失败	号码异常	-
	 * SYSTEM_ERROR	系统异常	未知	系统超时	需查询确认
	 * PARAM_ERROR	参数错误	提交失败	请求参数未按指引进行填写	请根据接口返回的详细信息检查您的程序
	 * SIGN_ERROR	签名错误	提交失败	参数签名结果不正确	请检查签名参数和方法是否都符合签名算法要求
	 * LACK_PARAMS	缺少参数	提交失败	缺少必要的请求参数	请检查参数是否齐全
	 * AGENT_NOT_EXIST	代理不存在	提交失败	无效的代理账号	请检查代理账号是否有效
	 * AGENT_ORDERID_USED	商户订单号重复	提交失败	同一笔交易不能多次提交	请核实商户订单号是否重复提交
	 * REQUIRE_POST_METHOD	请使用post方法	提交失败	未使用post传递参数	请检查请求参数是否通过post方法提交
	 * ILLEGAL_REQUEST	非法的请求	提交失败	请求IP与绑定的IP不符	请联系管理员更新绑定IP
	 * ORDER_NOT_EXISTS	订单不存在	提交失败	提交订单因网络异常提交失败	查询接口响应该参数，查询时间与下单时间相隔5分钟后，才可做失败处理
	 * ORDER_REVERSAL_SUCCESS	订单已是冲正成功状态	提交失败	订单已是冲正成功状态	该笔订单已是冲正成功状态，可直接处理为冲正成功
	 * ORDER_STATUS_NOT_SUCCESS	该笔订单不能冲正	提交失败	不为成功状态的订单不能冲正	订单状态非成功状态，不能进行冲正。请稍后再发起冲正请求
	 * REVERSAL_NOT_SUPPORT	该资源不能冲正	提交失败	不支持冲正的资源	请联系商务核实，确保是支持冲正资源
	 * REVERSAL_TIMEOUT	冲正超时	提交失败	该笔订单已超过冲正有效期	默认冲正时间不能超过24小时
	 * @param upOrder
	 * @param shopInfo
	 */

	/**
	 *
	 * agentAcct	代理账号	string(30)	Y	-
	 * orderId	订单编号	string(30)	Y	-
	 * sign	签名	string(32)	Y	MD5加密，详见签名规则
	 *
	 * 字段名称	字段说明	类型	必填	备注
	 * agentAcct	代理账号	string(30)	Y	-
	 * orderId	订单编号	string(30)	Y	-
	 * retCode	响应编码	string(30)	Y	SUCCESS仅表示查询成功
	 * retMsg	响应描述	string(50)	Y	不参与签名
	 * status	订单状态	string(10)	Y	详见订单状态编码列表
	 * voucher	充值凭证	string(50)	Y	充值成功时返回
	 * sign	签名	string(32)	Y	MD5加密，详见签名规则
	 * @return
	 */

	public void queryOrder(UpOrder upOrder, UpShopInfo shopInfo) {
		if(upOrder != null ){
			UpOrder product = upOrderService.findOrderProduct(upOrder.getUporderuuid());
			if (product != null) {
				JSONObject data = new JSONObject();
				data.put("agentAcct",shopInfo.getAppId());
				data.put("orderId",upOrder.getUporderuuid());
				data.put("sign",this.sign(data,"key",shopInfo.getUpkey()));
				String res = HttpClient.postUrl(shopInfo.getOrderStatusAddress(),StringSort.jsonToString(data));
				logger.info("queryZhengBang:"+res+"data:"+data+",phone:"+upOrder.getUpphonenum());
				if(res != null){
					JSONObject result = JSONObject.parseObject(res);
					if(result.containsKey("retCode")){
						if( result.getString("retCode").equals("SUCCESS") && result.getString("status").equals("S") ){
							UpOrder order = upOrderService.findById(upOrder.getUporderuuid());
							if(order != null && order != null && order.getStatus() == Config.status[0]){
								order.setRemark(result.containsKey("voucher") ? result.getString("voucher") : result.getString("status"));
								RechargeRest.successUpOrder.add(order);
							}
						}else if( result.getString("retCode").equals("SUCCESS") && result.getString("status").equals("F") ){
							UpOrder order = upOrderService.findById(upOrder.getUporderuuid());
							if( order != null && order.getStatus() == Config.status[0]){
								order.setRemark(result.containsKey("retMsg") ?	result.getString("retMsg") : Config.orderFailA);
								RechargeRest.failtUpOrder.add(order);
							}
						}
					}else{
						logger.debug("queryZhengBang查询失败:"+upOrder.getUpphonenum());
					}
				}else{
					logger.info("queryZhengBang order failt:"+upOrder.getUpphonenum());
				}
			}
		}else{
			logger.info("queryZhengBang order failt:"+upOrder.getUpphonenum());
		}
	}
}
